import Doc from '~/components/layout/docs'
import Link from '~/components/text/link'
import Snippet from '~/components/snippet'
import Caption from '~/components/text/caption'
import Note from '~/components/text/note'
import Card from '~/components/card'
import { InlineCode } from '~/components/text/code'
import CheckmarkInCircle from '~/components/icons/checkmark-in-circle'
import Center from '~/components/layout/center'

export const CenteredIcon = () => (
  <Center>
    <CheckmarkInCircle size="24" />
  </Center>
)

export const meta = {
  title: 'Build Step',
  description: 'Providing ZEIT Now with a build step.',
  editUrl: 'pages/docs/v2/build-step.mdx',
  lastEdited: '2020-02-03T16:11:46.000Z'
}

When you make a deployment with ZEIT Now, the first step is the build step. ZEIT Now recognizes a custom `build` script, with that build script outputting your app into the `public` directory.

ZEIT Now also supports optimized frameworks that only need to be created and then they are ready to deploy with [Now CLI](/download) from the terminal.

You are also able to use [environment variables](#using-environment-variables-and-secrets) (including secrets) in your builds if you do not want to hardcode values for the build.

<Note>
  If you are looking exclusively for an API only workflow, please take a look at
  our section on{' '}
  <Link href="/docs/v2/serverless-functions/introduction/">
    Serverless Functions
  </Link>
  .
</Note>

## Optimized Frameworks

A variety of frameworks have been optimized for ZEIT Now. The following list contains those frameworks that have been optimized and what has been done to aid their performance only on ZEIT Now. Any getting started method will immediately be ready to deploy with [Now CLI's `now` command](/download) from the terminal, or to be deployed with a [Git integration](/docs/v2/git-integration):

<Note>
  If you are using an{' '}
  <Link href="#optimized-frameworks">optimized framework</Link>, you must use
  the default output directory provided by the framework.
</Note>

<br />

| Framework        | Get Started Command                                 | Optimized                 |
| ---------------- | --------------------------------------------------- | ------------------------- |
| Next.js          | `npm init next-app my-next-project`                 | <CenteredIcon size="24"/> |
| Create React App | `npm init react-app my-cra-project`                 | <CenteredIcon size="24"/> |
| Vue.js           | `npx @vue/cli create my-vue-project`                | <CenteredIcon size="24"/> |
| Gatsby           | `npx gatsby-cli new my-gatsby-project`              | <CenteredIcon size="24"/> |
| Ember.js         | `npx ember-cli new my-ember-project`                | <CenteredIcon size="24"/> |
| Svelte           | `npx degit sveltejs/template my-svelte-project`     | <CenteredIcon size="24"/> |
| Stencil          | `npm init stencil`                                  | <CenteredIcon size="24"/> |
| Preact           | `npx preact-cli create default my-preact-project`   | <CenteredIcon size="24"/> |
| Angular          | `npx @angular/cli new my-angular-project`           | <CenteredIcon size="24"/> |
| Polymer          | `npx polymer-cli init polymer-3-starter-kit`        | <CenteredIcon size="24"/> |
| Gridsome         | `npx @gridsome/cli create my-gridsome-project`      | <CenteredIcon size="24"/> |
| UmiJS            | `npm init umi my-umi-project`                       | <CenteredIcon size="24"/> |
| Docusaurus       | `npx docusaurus-init`                               | <CenteredIcon size="24"/> |
| Saber            | `npm init site my-saber-project`                    | <CenteredIcon size="24"/> |
| 11ty/Eleventy    | `npx degit 11ty/eleventy-base-blog my-11ty-project` | <CenteredIcon size="24"/> |
| Hexo             | `npx hexo-cli init my-hexo-project`                 | <CenteredIcon size="24"/> |

## Defining a Build Script

To build your project, ZEIT Now looks for a `build` script inside of a `package.json` file. By providing a build script, ZEIT Now will build your project from fresh on every deployment.

For example, to build Next.js fresh, each time you deploy, the following `build` script should be placed in the `package.json`:

```json
{
  ...
  "scripts": {
    "build": "next build"
  }
}
```

<Caption>
  An example <InlineCode>package.json</InlineCode> file with a{' '}
  <InlineCode>build</InlineCode> script that builds Next.js on each deploy.
</Caption>

If you wish to use a script specific to ZEIT Now, you can override this behavior by providing a `now-build` script.

When ZEIT Now encounters a `package.json` file with both `build` and `now-build` scripts, only `now-build` will be used.

## Using Environment Variables and Secrets

When building your project, it may be necessary to use [environment variables](https://en.wikipedia.org/wiki/Environment_variable).

Adding environment variables requires two steps, defining the environment variable, then making it available to your projects' build step.

<Note>
  This section covers how to make environment variables available at{' '}
  <b>Build Time</b>, if you would like to make them available during{' '}
  <b>Run Time</b>, please see the{' '}
  <Link href="/docs/v2/serverless-functions/env-and-secrets/">
    Serverless Functions documentation
  </Link>
  .
</Note>

### Adding Secrets

To define an environment variable, you should use **Now Secrets**. By using **Now Secrets**, the data will be encrypted and stored securely, no longer directly accessible by anyone, and only exposed to deployments as environment variables.

Adding **Now Secrets** can be done with [Now CLI](/download), providing three options to work with them.

<Note>
  When adding Now Secrets with Now CLI, the secret name is automatically
  lowercased before being stored.
</Note>

To **define a Now Secret**, use the following command:

<Snippet dark text="now secrets add <secret-name> <secret-value>"/>
<Caption>Defining a <b>Now Secret</b> using <Link href="/now">Now CLI</Link>.</Caption>

To **remove a Now Secret**, use the following command:

<Snippet dark text="now secrets rm <secret-name>"/>
<Caption>Removing a <b>Now Secret</b> using <Link href="/now">Now CLI</Link>.</Caption>

To **rename a Now Secret**, use the following command:

<Snippet dark text="now secrets rename <secret-name> <new-name>"/>
<Caption>Renaming a <b>Now Secret</b> using <Link href="/now">Now CLI</Link>.</Caption>

### Providing Environment Variables

To provide your project with environment variables during the Build Step, you should create a `now.json` file like the one below:

```json
{
  "build": {
    "env": {
      "VARIABLE_NAME": "@secret-name"
    }
  }
}
```

<Caption>
  An example <InlineCode>now.json</InlineCode> file that provides an
  application's build step with a defined environment variable.
</Caption>

When providing environment variables to your application, the value should always be prefixed with `@`, followed by the name of the [Now Secret](#adding-secrets) or environment variable name if using a `.env.build` file [during local development](#during-local-development).

To use the environment variable from inside the application you would need to reference it using the correct syntax for the language being used. For example, using Node.js, the syntax would be:

```
process.env.VARIABLE_NAME
```

<Caption>
  Accessing a defined environment variable from within a Node.js application.
</Caption>

Now, whenever the `process.env.VARIABLE_NAME` key is used, it will provide the application's build step with the value declared by the referenced **Now Secret**.

## During Local Development

When using `now dev` to develop your application locally if you require the use of [Serverless Functions](/docs/v2/serverless-functions/introduction), [Now Secrets](#adding-secrets) are not available. This is a security measure, to prevent accidental use of production secrets during development.

To use environment variables during local development, create a `.env.build` file at the root of your project directory, for example:

```
VARIABLE_NAME=variable_value
```

<Caption>
  An example <InlineCode>.env.build</InlineCode> file that provides the Build
  Step with a defined environment variable.
</Caption>

<Note type="warning">
  Usage of a <InlineCode>.env.build</InlineCode> file is only possible during
  local development and will not be made available when deploying for security
  reasons.
</Note>

### Updating Environment Variables

Environment variables are made available to the build step, meaning that they do not update in the application unless it is redeployed.

If you change the value of a [Now Secret](#adding-secrets) or environment variable and want your application to be aware of this, you should create a new deployment.

### Reserved Variables

The ZEIT Now platform reserves the usage of some environment variable names by default. You can find a list of these names in the [limits documentation](/docs/v2/platform/limits/#reserved-variables).

## Ignored Files and Folders

By default, ZEIT Now ignores certain files and folders for security and performance reasons, preventing them from being uploaded during the deployment process.

```bash
.hg
.git
.gitmodules
.svn
.cache
.next
.now
.npmignore
.dockerignore
.gitignore
.*.swp
.DS_Store
.wafpicke-*
.lock-wscript
.env
.env.*
.venv
npm-debug.log
config.gypi
node_modules
__pycache__/
venv/
CVS
```

<Caption>
  A complete list of files and folders ignored by ZEIT Now during the deployment
  process.
</Caption>

<Note>
  You do not need to add any of the above files and folders to your{' '}
  <InlineCode>.nowignore</InlineCode> file.
</Note>

## Technical Details

### Maximum Build Duration

A build can last for a maximum of 30 minutes. If the build exceeds this time, the deployment will error.

### Caching

Each build step will cache files used to build the project, or files used in subsequent deployments, such as `node_modules`, `yarn.lock`, `package-lock.json`, which are cached by default.

The caching mechanism for builds ensures that the next deployment will happen quicker by skipping downloading files that have already been used in a previous deployment.

The maximum stored cache for builds is 3Gb.

If a deployment fails, a cache may still be established for successfully built files, but failed builds will not be cached.

### Private npm Modules for Static Builds

To install private npm modules, define `NPM_TOKEN` as a [build environment variable](/docs/configuration#project/build-env) in a `now.json` file.

Alternatively, define `NPM_RC` as a [build environment variable](/docs/configuration#project/build-env) with the contents of `~/.npmrc`.

### Prevent Cache Usage

If you need to ignore the cache for a deployment, you can do so by using the [`-f` flag for Now CLI](/docs/now-cli/#commands/now/global-options). This prevents the cache from being used in the deployment and ensures a fresh install for all dependencies.

### Framework Versioning

Some frameworks do not use `package.json` to select a specific version to install during build time.

By including [a `build.env` configuration property](/docs/configuration#project/build-env) in [a `now.json` file](/docs/configuration) at your project's root, you can define your framework's version with one of the following keys:

| Framework | Build Env Key  |
| --------- | -------------- |
| Hugo      | `HUGO_VERSION` |
| Zola      | `ZOLA_VERSION` |

For example, defining the Hugo version in a `now.json` file would look like the following snippet:

```json
{
  "build": {
    "env": {
      "HUGO_VERSION": "0.61.0"
    }
  }
}
```

<Caption>
  An example of defining a version for Hugo with a{' '}
  <InlineCode>now.json</InlineCode> configuration.
</Caption>

<Note>
  The value must match an existing GitHub Release with an attached asset. For
  example, Hugo{' '}
  <InlineCode>
    <Link href="https://github.com/gohugoio/hugo/releases/tag/v0.42.0">
      0.42.0
    </Link>
  </InlineCode>{' '}
  does not exist but Hugo{' '}
  <InlineCode>
    <Link href="https://github.com/gohugoio/hugo/releases/tag/v0.42">0.42</Link>
  </InlineCode>{' '}
  does exist.
</Note>

## Related

For more information on what to do next, we recommend the following articles:

<Card title="Git Integration" href="/docs/v2/git-integration">
  Learn more about how ZEIT Now integrates with Git to make your workflow
  easier.
</Card>

<Card title="Deploy Hooks" href="/docs/v2/advanced/deploy-hooks">
  Use Deploy Hooks to trigger deployments to build content from outside ZEIT.
</Card>

export default ({ children }) => <Doc meta={meta}>{children}</Doc>

export const config = {
  amp: 'hybrid'
}
